← Back

Pagination in JavaScript

Pagination means splitting a large collection of data into smaller parts.

Instead of loading everything at once, the server sends only one small group of records.

You will learn:

  1. what pagination is
  2. why loading all data at once is a bad idea
  3. how _limit works
  4. how _page works
  5. how to load data in groups
  6. how the Load more button works
  7. how to detect the end of the collection
  8. how to calculate the number of pages

1. What is pagination?

Pagination means loading data in small groups, not all at once.

For example:

Pagination = loading data in small groups, not all at once
Big collection
-> split into smaller groups
-> load one group at a time

If a database has thousands of records, it is not practical to load everything in one request.

2. Why avoid loading the whole collection?

If a collection is very large, loading everything at once causes problems.

Too much data at once
|
|- browser works harder
|- network is slower
|- server works harder
`- user sees only first part anyway

Pagination solves these problems by sending data in smaller pieces.

3. Example without pagination

Suppose we request all posts:

const fetchPosts = async () => {
  const response = await axios.get("https://jsonplaceholder.typicode.com/posts");
  console.log("Posts: ", response.data);
};

This gets the whole /posts collection.

Request all posts
-> server sends full collection
-> browser receives everything

That may work for small examples, but in a real application it is often inefficient.

4. Limiting the number of items

The first step of pagination is limiting how many records come back in one response.

Different backends may use different parameter names, for example:

There is no universal rule. The parameter name depends on the backend.

In JSONPlaceholder, the parameter is _limit.

Collection has many records
-> _limit tells server:
   "send only this many"

5. Example with _limit

const fetchPosts = async () => {
  const response = await axios.get("https://jsonplaceholder.typicode.com/posts?_limit=5");
  console.log("Posts: ", response.data);
};

Here the server does not send all posts. It sends only 5 posts.

_limit=5
= return only 5 records
/posts
-> apply _limit=5
-> only 5 posts are returned

This is the foundation of pagination. First, decide how many items should be in one group.

6. What if _limit is wrong?

If you send a strange value, such as a negative number or a number larger than expected, the server may behave differently depending on its implementation.

It may:

So always use reasonable values.

7. Getting the next group of records

If you only use _limit, you always get the first group.

_limit=5
= first 5 records

But if you want the next 5 records, you need the second pagination parameter: _page.

In other APIs it may be called page.

_limit = how many items
_page  = which group of items

Pagination usually needs both the size of the group and the number of the group.

8. Example with _limit and _page

const fetchPosts = async () => {
  const response = await axios.get("https://jsonplaceholder.typicode.com/posts?_limit=5&_page=3");
  console.log("Posts: ", response.data);
};

Here:

Page 1 - records 1-5
Page 2 - records 6-10
Page 3 - records 11-15

The page number tells the server which group to return.

9. How page groups work

If _limit = 5, the groups look like this:

Page 1 - 1-5
Page 2 - 6-10
Page 3 - 11-15
Page 4 - 16-20
...
Full collection
|
|- Page 1
|- Page 2
|- Page 3
|- Page 4
`- ...

Pagination means moving through the collection group by group.

10. Why _page is useful

Without _page, you always receive the same first records.

With _page, you can move forward through the collection.

_limit controls group size
_page controls group number

11. Backend metadata

Some APIs return extra information together with the data, for example:

This is useful because the frontend can understand when the collection ends.

If the backend returns total items, you can calculate total pages.

total_pages = total_items / per_page

In practice, it is safer to round up:

Math.ceil(totalItems / perPage)
total items
/
items per page
-> total pages

If the division gives a decimal number, round up because even a partly filled last page still counts as one page.

12. Important correction: use Math.ceil()

If there are 100 posts and 30 posts per page:

Math.ceil(100 / 30)

Result:

4

Because:

100 items
/ 30 per page
= 3.33...
-> round up
-> 4 pages

Even though the last page is not full, it still exists.

13. JSONPlaceholder limitation

JSONPlaceholder supports _limit and _page, but it does not give full pagination metadata in the way many real APIs do.

So in this lesson, the end-of-collection logic is implemented on the frontend manually.

That means the frontend developer must decide how many total records exist and calculate the total number of pages.

14. The Load more technique

A common interface pattern is the Load more button.

Instead of showing all posts immediately:

Click button
-> load page 1
-> show records

Click again
-> load page 2
-> add records below

Click again
-> load page 3
-> add more records

This way the page grows step by step instead of loading everything at once.

15. How the Load more logic works

The usual logic is:

  1. create a variable page
  2. set it to 1
  3. after each successful request, increase page
  4. use the new value for the next request
let page = 1;
const limit = 5;

Then after a successful request:

page += 1;
Start:
page = 1

After first request:
page = 2

After second request:
page = 3

After third request:
page = 4

The page variable remembers which group should be loaded next.

16. Example of paginated request with variables

let page = 1;
const limit = 5;

const fetchPosts = async () => {
  const response = await axios.get("https://jsonplaceholder.typicode.com/posts", {
    params: {
      _limit: limit,
      _page: page,
    },
  });

  console.log(response.data);
  page += 1;
};

This version is cleaner because _limit uses a variable, _page uses a variable, and page changes after each request.

17. Adding new records to the page

When the next page is loaded, you usually do not replace the old list.

You append the new records below the old ones.

So the user sees:

First click
-> [posts 1-5]

Second click
-> [posts 1-5]
   [posts 6-10]

Third click
-> [posts 1-5]
   [posts 6-10]
   [posts 11-15]

This is why Load more feels natural.

18. Checking the end of the collection

At some point, there are no more posts to load.

So before making a new request, the app should check whether more pages still exist.

If not, it should show a message like:

We're sorry, there are no more posts to load

This improves UX because the user understands that loading is finished.

Current page > total pages?
|- yes -> show message
`- no  -> send next request

19. Calculating total pages

let limit = 30;
const totalPages = Math.ceil(100 / limit);

Here:

Result:

4
limit = 30
total items = 100

100 / 30 = 3.33...
Math.ceil(3.33...) = 4

So there are 4 pages total.

20. Check before sending the next request

Before the next request, compare the current page with totalPages.

if (page > totalPages) {
  return iziToast.error({
    position: "topRight",
    message: "We're sorry, there are no more posts to load"
  });
}

If page is already bigger than totalPages, then all records are already loaded.

Before request
-> Is page > totalPages?
   |- yes -> stop and show message
   `- no  -> continue request

21. Why this check is useful

This check gives two benefits:

  1. It avoids useless requests because there is no need to ask the server for data that does not exist.
  2. It improves user experience because the user gets clear feedback that the collection is finished.
End check
|
|- avoids unnecessary server requests
`- improves UX

22. Full pagination idea in one view

Pagination usually works like this:

  1. choose limit
  2. start with page = 1
  3. request records with _limit and _page
  4. render them
  5. increase page
  6. stop when all pages are loaded
Set limit
-> Set page = 1
-> Request page 1
-> Render posts
-> Increase page
-> Request next page
-> Repeat until page > totalPages

23. Common beginner mistakes

const totalPages = 100 / 30;

Better:

const totalPages = Math.ceil(100 / 30);
Need pagination?
-> Use limit
-> Use page
-> Increase page after success
-> Use Math.ceil for total pages
-> Check collection end before next request

24. Easy memory rules

Pagination = load data in groups
_limit = how many items
_page = which group
page += 1 = move to next group
Math.ceil(totalItems / limit) = total pages
if page > totalPages = stop loading

25. Quick summary

26. Final conclusion

If you understand these ideas, you already have a strong foundation for using pagination in JavaScript:

pagination
_limit
_page
page variable
Load more
totalPages
Math.ceil
end of collection

Pagination is very important in real applications because large collections are everywhere: posts, products, comments, users, and search results.

← Back